/**
 * 设备发现服务
 * 整合蓝牙和WiFi设备发现逻辑，提高搜索效率
 */

const logger = require('../utils/logger').logger;
const networkManager = require('../utils/network-manager');
const BluetoothService = require('./bluetooth-service').getInstance;
const WifiService = require('./wifi-service').getInstance;
const DeviceService = require('./device-service').getInstance;
const envDetector = require('../utils/env-detector');
const AppConfig = require('../config/app.config');

// 设备发现方法枚举
const DISCOVERY_METHOD = {
  AUTO: 'auto',         // 自动选择最佳方式
  BLUETOOTH: 'bluetooth', // 仅使用蓝牙发现
  WIFI: 'wifi',         // 仅使用WiFi发现
  BOTH: 'both'          // 同时使用蓝牙和WiFi发现
};

// 设备类型前缀映射
const DEVICE_PREFIX_MAP = {
  'freshwater_lamp': 'FW-LAMP-',
  'seawater_lamp': 'SW-LAMP-',
  'freshwater_diy_lamp': 'FW-DIY-',
  'seawater_diy_lamp': 'SW-DIY-'
};

/**
 * 设备发现管理器类
 */
class DeviceDiscovery {
  constructor() {
    // 设备发现结果
    this.discoveredDevices = new Map();
    
    // 是否正在搜索中
    this.isSearching = false;
    
    // 是否在开发者工具中运行
    this.isDevTools = envDetector.isDevTools();
    
    // 搜索超时
    this.searchTimeout = null;
    
    // 获取蓝牙和WiFi服务实例
    this.bluetoothService = BluetoothService();
    this.wifiService = WifiService();
    this.deviceService = DeviceService();
    
    logger.info('设备发现服务初始化完成');
  }
  
  /**
   * 开始搜索设备
   * @param {Object} options 搜索选项
   * @param {string} options.method 搜索方法，默认为AUTO
   * @param {number} options.timeout 搜索超时时间（毫秒），默认为15000
   * @param {Array<string>} options.deviceTypes 要搜索的设备类型数组
   * @param {Function} options.onDeviceFound 发现设备回调
   * @param {Function} options.onSearchComplete 搜索完成回调
   * @returns {Promise<Array>} 搜索到的设备数组
   */
  startDiscovery(options = {}) {
    // 如果已在搜索中，先停止
    if (this.isSearching) {
      this.stopDiscovery();
    }
    
    // 重置发现结果
    this.discoveredDevices.clear();
    
    // 设置默认选项
    const searchOptions = {
      method: options.method || DISCOVERY_METHOD.AUTO,
      timeout: options.timeout || 15000,
      deviceTypes: options.deviceTypes || Object.keys(DEVICE_PREFIX_MAP),
      onDeviceFound: options.onDeviceFound || (() => {}),
      onSearchComplete: options.onSearchComplete || (() => {})
    };
    
    // 标记为搜索中
    this.isSearching = true;
    
    logger.info('开始搜索设备', {
      method: searchOptions.method,
      timeout: searchOptions.timeout,
      deviceTypes: searchOptions.deviceTypes
    });
    
    // 根据搜索方法和网络环境决定实际搜索方式
    const actualMethod = this._determineSearchMethod(searchOptions.method);
    
    // 在开发者工具中模拟设备搜索
    if (this.isDevTools) {
      return this._mockDeviceDiscovery(searchOptions);
    }
    
    // 创建搜索Promise
    return new Promise((resolve) => {
      // 设置搜索超时
      this.searchTimeout = setTimeout(() => {
        // 停止搜索
        this._stopSearching(actualMethod);
        
        // 回调搜索完成
        const devices = Array.from(this.discoveredDevices.values());
        searchOptions.onSearchComplete(devices);
        
        // 解析Promise
        resolve(devices);
      }, searchOptions.timeout);
      
      // 根据搜索方法启动相应的搜索
      if (actualMethod === DISCOVERY_METHOD.BLUETOOTH || actualMethod === DISCOVERY_METHOD.BOTH) {
        this._startBluetoothDiscovery(searchOptions);
      }
      
      if (actualMethod === DISCOVERY_METHOD.WIFI || actualMethod === DISCOVERY_METHOD.BOTH) {
        this._startWifiDiscovery(searchOptions);
      }
    });
  }
  
  /**
   * 确定实际的搜索方法
   * @param {string} requestedMethod 请求的搜索方法
   * @returns {string} 实际的搜索方法
   * @private
   */
  _determineSearchMethod(requestedMethod) {
    // 如果指定了具体方法，则使用指定的方法
    if (requestedMethod !== DISCOVERY_METHOD.AUTO) {
      return requestedMethod;
    }
    
    // 根据网络环境自动选择最佳搜索方法
    const networkType = networkManager.getNetworkType();
    
    // 在WiFi环境下，优先使用WiFi发现，但也启用蓝牙作为备选
    if (networkType === 'wifi') {
      return DISCOVERY_METHOD.BOTH;
    }
    
    // 在移动网络或无网络环境下，仅使用蓝牙发现
    return DISCOVERY_METHOD.BLUETOOTH;
  }
  
  /**
   * 开始蓝牙设备搜索
   * @param {Object} searchOptions 搜索选项
   * @private
   */
  _startBluetoothDiscovery(searchOptions) {
    logger.info('开始蓝牙设备搜索');
    
    // 构建设备名前缀过滤器
    const nameFilters = searchOptions.deviceTypes.map(type => DEVICE_PREFIX_MAP[type]).filter(Boolean);
    
    // 开始蓝牙搜索
    this.bluetoothService.startDeviceDiscovery({
      namePrefix: nameFilters,
      allowDuplicatesKey: false,
      onDeviceFound: (device) => {
        // 解析设备信息
        const parsedDevice = this._parseBluetoothDevice(device, searchOptions.deviceTypes);
        
        if (parsedDevice) {
          // 添加到发现结果
          this.discoveredDevices.set(parsedDevice.id, parsedDevice);
          
          // 触发设备发现回调
          searchOptions.onDeviceFound(parsedDevice);
        }
      },
      onError: (error) => {
        logger.error('蓝牙设备搜索错误', error);
      }
    });
  }
  
  /**
   * 开始WiFi设备搜索
   * @param {Object} searchOptions 搜索选项
   * @private
   */
  _startWifiDiscovery(searchOptions) {
    logger.info('开始WiFi设备搜索');
    
    // 构建设备类型过滤器
    const typeFilters = searchOptions.deviceTypes;
    
    // 开始WiFi设备扫描
    this.wifiService.startDeviceScan({
      deviceTypes: typeFilters,
      onDeviceFound: (device) => {
        // 解析设备信息
        const parsedDevice = this._parseWifiDevice(device);
        
        if (parsedDevice) {
          // 添加到发现结果
          this.discoveredDevices.set(parsedDevice.id, parsedDevice);
          
          // 如果同一设备已经通过蓝牙发现，合并信息
          this._mergeDeviceInfo(parsedDevice);
          
          // 触发设备发现回调
          searchOptions.onDeviceFound(parsedDevice);
        }
      },
      onError: (error) => {
        logger.error('WiFi设备搜索错误', error);
      }
    });
  }
  
  /**
   * 合并设备信息
   * @param {Object} device 设备信息
   * @private
   */
  _mergeDeviceInfo(device) {
    const existingDevice = this.discoveredDevices.get(device.id);
    
    if (existingDevice) {
      // 合并设备信息，保留更多的信息
      const mergedDevice = {
        ...existingDevice,
        ...device,
        // 记录可通过的连接方式
        connectionMethods: Array.from(
          new Set([
            ...(existingDevice.connectionMethods || []),
            ...(device.connectionMethods || [])
          ])
        )
      };
      
      this.discoveredDevices.set(device.id, mergedDevice);
    }
  }
  
  /**
   * 解析蓝牙设备信息
   * @param {Object} device 蓝牙设备
   * @param {Array<string>} allowedTypes 允许的设备类型
   * @returns {Object|null} 解析后的设备信息或null
   * @private
   */
  _parseBluetoothDevice(device, allowedTypes) {
    try {
      const { deviceId, name, advertisData, RSSI } = device;
      
      // 检查设备名称是否符合规则
      if (!name) return null;
      
      // 确定设备类型
      let deviceType = null;
      
      for (const type of allowedTypes) {
        const prefix = DEVICE_PREFIX_MAP[type];
        if (prefix && name.startsWith(prefix)) {
          deviceType = type;
          break;
        }
      }
      
      // 如果设备类型不在允许列表中，跳过
      if (!deviceType) return null;
      
      // 从设备名称中提取设备ID
      const id = name.split('-').pop();
      
      if (!id) return null;
      
      // 解析广播数据中的设备信息
      let manufacturerData = null;
      let isFreshwater = deviceType.includes('freshwater');
      let isDIY = deviceType.includes('diy');
      
      if (advertisData && advertisData.manufacturerData) {
        try {
          // 解析厂商数据
          const dataView = new DataView(advertisData.manufacturerData);
          manufacturerData = {
            batteryLevel: dataView.getUint8(0),
            temperature: dataView.getUint8(1)
          };
        } catch (e) {
          logger.warn('解析蓝牙设备厂商数据失败', e);
        }
      }
      
      // 构建设备信息
      return {
        id,
        name: `${isFreshwater ? '淡水' : '海水'}${isDIY ? 'DIY' : ''}灯`,
        deviceId,
        deviceType,
        connectionMethods: ['bluetooth'],
        rssi: RSSI,
        batteryLevel: manufacturerData ? manufacturerData.batteryLevel : 100,
        temperature: manufacturerData ? manufacturerData.temperature : null,
        discoveryTime: Date.now(),
        isFreshwater,
        isDIY
      };
    } catch (e) {
      logger.error('解析蓝牙设备失败', e);
      return null;
    }
  }
  
  /**
   * 解析WiFi设备信息
   * @param {Object} device WiFi设备
   * @returns {Object|null} 解析后的设备信息或null
   * @private
   */
  _parseWifiDevice(device) {
    try {
      const { deviceId, name, type, ipAddress, port, deviceInfo } = device;
      
      // 确保基本信息完整
      if (!deviceId || !type) return null;
      
      // 从设备类型确定是淡水还是海水，是否DIY
      const isFreshwater = type.includes('freshwater');
      const isDIY = type.includes('diy');
      
      // 构建设备信息
      return {
        id: deviceId,
        name: name || `${isFreshwater ? '淡水' : '海水'}${isDIY ? 'DIY' : ''}灯`,
        deviceType: type,
        connectionMethods: ['wifi'],
        ipAddress,
        port,
        discoveryTime: Date.now(),
        batteryLevel: deviceInfo ? deviceInfo.batteryLevel : 100,
        temperature: deviceInfo ? deviceInfo.temperature : null,
        isFreshwater,
        isDIY
      };
    } catch (e) {
      logger.error('解析WiFi设备失败', e);
      return null;
    }
  }
  
  /**
   * 在开发者工具中模拟设备发现
   * @param {Object} searchOptions 搜索选项
   * @returns {Promise<Array>} 模拟的设备数组
   * @private
   */
  _mockDeviceDiscovery(searchOptions) {
    logger.info('在开发者工具中模拟设备发现');
    
    // 创建搜索Promise
    return new Promise((resolve) => {
      // 模拟设备列表
      const mockDevices = this._generateMockDevices(searchOptions.deviceTypes);
      
      // 模拟设备发现过程
      let foundCount = 0;
      
      const discoverInterval = setInterval(() => {
        if (foundCount >= mockDevices.length || !this.isSearching) {
          clearInterval(discoverInterval);
          
          // 如果仍在搜索，则完成搜索
          if (this.isSearching) {
            // 停止搜索
            this.isSearching = false;
            
            // 清除超时
            if (this.searchTimeout) {
              clearTimeout(this.searchTimeout);
              this.searchTimeout = null;
            }
            
            // 回调搜索完成
            const devices = Array.from(this.discoveredDevices.values());
            searchOptions.onSearchComplete(devices);
            
            // 解析Promise
            resolve(devices);
          }
          
          return;
        }
        
        // 获取下一个要"发现"的设备
        const device = mockDevices[foundCount++];
        
        // 添加到发现结果
        this.discoveredDevices.set(device.id, device);
        
        // 触发设备发现回调
        searchOptions.onDeviceFound(device);
      }, 800); // 每800ms发现一个设备
      
      // 设置搜索超时
      this.searchTimeout = setTimeout(() => {
        clearInterval(discoverInterval);
        
        this.isSearching = false;
        
        // 回调搜索完成
        const devices = Array.from(this.discoveredDevices.values());
        searchOptions.onSearchComplete(devices);
        
        // 解析Promise
        resolve(devices);
      }, searchOptions.timeout);
    });
  }
  
  /**
   * 生成模拟设备
   * @param {Array<string>} deviceTypes 设备类型数组
   * @returns {Array<Object>} 模拟设备数组
   * @private
   */
  _generateMockDevices(deviceTypes) {
    const mockDevices = [];
    
    // 为每种设备类型生成1-3个模拟设备
    deviceTypes.forEach(type => {
      const count = Math.floor(Math.random() * 3) + 1;
      
      for (let i = 0; i < count; i++) {
        const id = `${this._generateRandomHex(8)}`;
        const isFreshwater = type.includes('freshwater');
        const isDIY = type.includes('diy');
        const useWifi = Math.random() > 0.3; // 70%的设备支持WiFi
        const useBluetooth = Math.random() > 0.2 || !useWifi; // 80%的设备支持蓝牙，如果不支持WiFi则一定支持蓝牙
        
        const connectionMethods = [];
        if (useBluetooth) connectionMethods.push('bluetooth');
        if (useWifi) connectionMethods.push('wifi');
        
        // 构建模拟设备
        mockDevices.push({
          id,
          name: `${isFreshwater ? '淡水' : '海水'}${isDIY ? 'DIY' : ''}灯 ${id.substring(0, 4)}`,
          deviceId: useBluetooth ? `mockBLE_${id}` : null,
          deviceType: type,
          connectionMethods,
          rssi: useBluetooth ? -Math.floor(Math.random() * 60 + 40) : null, // -40 到 -100 之间
          ipAddress: useWifi ? `192.168.1.${Math.floor(Math.random() * 254) + 1}` : null,
          port: useWifi ? 8080 : null,
          batteryLevel: Math.floor(Math.random() * 100) + 1,
          temperature: Math.floor(Math.random() * 15) + 20, // 20-35°C
          discoveryTime: Date.now() - Math.floor(Math.random() * 5000),
          isFreshwater,
          isDIY
        });
      }
    });
    
    return mockDevices;
  }
  
  /**
   * 生成随机十六进制字符串
   * @param {number} length 字符串长度
   * @returns {string} 随机十六进制字符串
   * @private
   */
  _generateRandomHex(length) {
    let result = '';
    const characters = '0123456789ABCDEF';
    
    for (let i = 0; i < length; i++) {
      result += characters.charAt(Math.floor(Math.random() * characters.length));
    }
    
    return result;
  }
  
  /**
   * 停止搜索设备
   */
  stopDiscovery() {
    if (!this.isSearching) return;
    
    logger.info('停止设备搜索');
    
    // 停止蓝牙和WiFi搜索
    this._stopSearching();
    
    // 标记为未搜索
    this.isSearching = false;
    
    // 清除超时
    if (this.searchTimeout) {
      clearTimeout(this.searchTimeout);
      this.searchTimeout = null;
    }
  }
  
  /**
   * 停止实际的搜索过程
   * @param {string} method 搜索方法
   * @private
   */
  _stopSearching(method = DISCOVERY_METHOD.BOTH) {
    // 停止蓝牙搜索
    if (method === DISCOVERY_METHOD.BLUETOOTH || method === DISCOVERY_METHOD.BOTH) {
      this.bluetoothService.stopDeviceDiscovery().catch(err => {
        logger.warn('停止蓝牙设备搜索失败', err);
      });
    }
    
    // 停止WiFi搜索
    if (method === DISCOVERY_METHOD.WIFI || method === DISCOVERY_METHOD.BOTH) {
      this.wifiService.stopDeviceScan().catch(err => {
        logger.warn('停止WiFi设备搜索失败', err);
      });
    }
  }
  
  /**
   * 获取已发现的设备列表
   * @returns {Array<Object>} 设备列表
   */
  getDiscoveredDevices() {
    return Array.from(this.discoveredDevices.values());
  }
  
  /**
   * 获取设备详细信息
   * @param {string} deviceId 设备ID
   * @returns {Promise<Object>} 设备详细信息
   */
  getDeviceDetails(deviceId) {
    // 首先检查是否在已发现设备中
    const cachedDevice = this.discoveredDevices.get(deviceId);
    
    if (!cachedDevice) {
      return Promise.reject(new Error('设备未发现'));
    }
    
    // 如果在开发者工具中，返回模拟数据
    if (this.isDevTools) {
      return Promise.resolve({
        ...cachedDevice,
        firmwareVersion: '1.2.3',
        hardwareVersion: 'A1',
        supportedFeatures: ['timers', 'rgb', 'white', 'fan'],
        maxChannels: cachedDevice.isDIY ? 10 : 6,
        lastConnected: Date.now() - 86400000 * Math.floor(Math.random() * 7)
      });
    }
    
    // 根据设备支持的连接方式选择获取详情的方法
    const connectionMethods = cachedDevice.connectionMethods || [];
    
    // 优先使用WiFi获取详情
    if (connectionMethods.includes('wifi')) {
      return this._getDeviceDetailsViaWifi(cachedDevice);
    }
    
    // 如果不支持WiFi，则使用蓝牙
    if (connectionMethods.includes('bluetooth')) {
      return this._getDeviceDetailsViaBluetooth(cachedDevice);
    }
    
    return Promise.reject(new Error('设备没有可用的连接方式'));
  }
  
  /**
   * 通过WiFi获取设备详情
   * @param {Object} device 设备信息
   * @returns {Promise<Object>} 设备详细信息
   * @private
   */
  _getDeviceDetailsViaWifi(device) {
    return this.deviceService.getDeviceInfo(device.id, 'wifi');
  }
  
  /**
   * 通过蓝牙获取设备详情
   * @param {Object} device 设备信息
   * @returns {Promise<Object>} 设备详细信息
   * @private
   */
  _getDeviceDetailsViaBluetooth(device) {
    return this.deviceService.getDeviceInfo(device.id, 'bluetooth');
  }
  
  /**
   * 清除设备搜索结果
   */
  clearDiscoveredDevices() {
    this.discoveredDevices.clear();
  }
}

// 导出搜索方法枚举
DeviceDiscovery.DISCOVERY_METHOD = DISCOVERY_METHOD;

// 导出单例
const deviceDiscovery = new DeviceDiscovery();
module.exports = deviceDiscovery; 